/*
 * WorstFitArea.cpp
 *
 *  Created on: 04.03.2011
 *      Author: marco
 */

#include "WorstFitArea.h"
#include <assert.h>

WorstFitArea::WorstFitArea(WorstFitAreaType my_type, int base, int size,
		WorstFitArea* my_previous, WorstFitArea* my_next) : Area(base, size) {
	type = my_type;
	previous = my_previous;
	next = my_next;

}

WorstFitArea* WorstFitArea::getNext() {
	return next;
}
WorstFitArea* WorstFitArea::getPrevious() {
	return previous;
}

bool WorstFitArea::hasNext() {
	return next != 0;
}

bool WorstFitArea::hasPrevious() {
	return previous != 0;
}

WorstFitAreaType WorstFitArea::getType() {
	return type;
}

WorstFitArea* WorstFitArea::allocate(int process_size) {
	assert(process_size <= getSize());
	assert(process_size > 0);

	if (process_size == getSize()) {
		type = process;
	} else {
		WorstFitArea* tmp = next;
		next = new WorstFitArea(hole, getBase() + process_size, getSize() - process_size, this, tmp);
		if (tmp != 0)
			tmp->setPrevious(next);
		setSize(process_size);
		type = process;
	}
	return this;
}

void WorstFitArea::free() {
	if (type==hole)
		return;
	if (previousIsHole() && nextIsHole()) {
		WorstFitArea* tmp = getNext();
		getPrevious()->setNext(getNext()->getNext());
		getPrevious()->setSize(getPrevious()->getSize() + size + getNext()->getSize());
		if (getNext()->hasNext())
			getNext()->getNext()->setPrevious(getPrevious());
	} else if (previousIsHole()) {
		getPrevious()->setSize(getPrevious()->getSize() + size);
		getPrevious()->setNext(getNext());
	} else if (nextIsHole()) {
		WorstFitArea* tmp = getNext();
		setSize(size + getNext()->getSize());
		if (getNext()->hasNext())
			getNext()->getNext()->setPrevious(this);
		setNext(getNext()->getNext());
	}
	type = hole;

}

bool WorstFitArea::previousIsHole() {
	return (hasPrevious() && previous->getType() == hole);
}
bool WorstFitArea::nextIsHole() {
	return (hasNext() && next->getType() == hole);
}

void WorstFitArea::setPrevious(WorstFitArea* new_previous) {
	previous = new_previous;
}

void WorstFitArea::setNext(WorstFitArea* new_next) {
	next = new_next;
}

void WorstFitArea::setBase(int new_base) {
	base = new_base;
	ends = base + size - 1;
}
void WorstFitArea::setSize(int new_size) {
	size = new_size;
	ends = base + size - 1;
}

WorstFitArea::~WorstFitArea() {
	// TODO Auto-generated destructor stub
}
